﻿using System.Collections.Generic;
using System.ComponentModel;
using Zive.Color;

namespace LabColorPicker {

    public class ColorData: INotifyPropertyChanged {

        public ColorData( ) {
            _rgbColor = new RgbColor( );
            _labColor = new LabColor( );
            _xyzColor = new XyzColor( );

            _HookPropertyChangedEvents( );
        }

        public ColorData( ColorData orig ) {
            _rgbColor = new RgbColor( orig._rgbColor );
            _labColor = new LabColor( orig._labColor );
            _xyzColor = new XyzColor( orig._xyzColor );

            _HookPropertyChangedEvents( );
        }

        private RgbColor _rgbColor;
        public RgbColor Rgb {
            get { return _rgbColor; }
            set { _Update( value ); }
        }

        private LabColor _labColor;
        public LabColor Lab {
            get { return _labColor; }
            set { _Update( value ); }
        }

        private XyzColor _xyzColor;
        public XyzColor Xyz {
            get { return _xyzColor; }
            set { _Update( value ); }
        }

        private void RgbColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _rgbColor );
        }

        private void LabColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _labColor );
        }

        private void XyzColor_PropertyChanged( object sender, PropertyChangedEventArgs ev ) {
            _Update( _xyzColor );
        }

        private void _HookPropertyChangedEvents( ) {
            if ( null != _labColor ) {
                _labColor.PropertyChanged += LabColor_PropertyChanged;
            }
            if ( null != _rgbColor ) {
                _rgbColor.PropertyChanged += RgbColor_PropertyChanged;
            }
            if ( null != _xyzColor ) {
                _xyzColor.PropertyChanged += XyzColor_PropertyChanged;
            }
        }

        private void _UnhookPropertyChangedEvents( ) {
            if ( null != _labColor ) {
                _labColor.PropertyChanged -= LabColor_PropertyChanged;
            }
            if ( null != _rgbColor ) {
                _rgbColor.PropertyChanged -= RgbColor_PropertyChanged;
            }
            if ( null != _xyzColor ) {
                _xyzColor.PropertyChanged -= XyzColor_PropertyChanged;
            }
        }

        private void _Update( RgbColor value ) {
            _UnhookPropertyChangedEvents( );

            _rgbColor = value;
            _xyzColor = _rgbColor.ToXyzColor( );
            _labColor = _xyzColor.ToLabColor( );

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Xyz" );
        }

        private void _Update( LabColor value ) {
            _UnhookPropertyChangedEvents( );

            _labColor = value;
            _xyzColor = _labColor.ToXyzColor( );
            _rgbColor = _xyzColor.ToSrgbColor( );

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Xyz" );
        }

        private void _Update( XyzColor value ) {
            _UnhookPropertyChangedEvents( );

            _xyzColor = value;
            _labColor = _xyzColor.ToLabColor( );
            _rgbColor = _xyzColor.ToSrgbColor( );

            _HookPropertyChangedEvents( );

            _OnPropertyChanged( "Lab" );
            _OnPropertyChanged( "Rgb" );
            _OnPropertyChanged( "Xyz" );
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void _OnPropertyChanged( string propertyName ) {
            var handlers = PropertyChanged;
            if ( null != handlers ) {
                handlers( this, new PropertyChangedEventArgs( propertyName ) );
            }
        }

        #endregion

    }

}
